package com.baoteng.rbspy.mq;

import java.time.ZoneId;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import com.baoteng.rbspy.cache.LocalCacheManager;
import com.baoteng.rbspy.config.car.RbSysConfig;
import com.baoteng.rbspy.exception.BizException;
import com.baoteng.rbspy.exception.VehicleCodeException;
import com.baoteng.rbspy.model.proposal.DetailsProposal;
import com.baoteng.rbspy.model.proposal.InfoFlow;
import com.baoteng.rbspy.model.proposal.InfoPolicy;
import com.baoteng.rbspy.model.proposal.InfoProposal;
import com.baoteng.rbspy.model.renewal.RenewalPO;
import com.baoteng.rbspy.model.request.RenewalRequest;
import com.baoteng.rbspy.model.vehicle.VehiclePO;
import com.baoteng.rbspy.service.ProposalService;
import com.baoteng.rbspy.service.QuoteService;
import com.baoteng.rbspy.service.RenewalService;
import com.baoteng.rbspy.util.BaseUtil;
import com.baoteng.rbspy.util.JsonUtils;
import com.baoteng.rbspy.vo.request.ApplyInsureRequest;
import com.baoteng.rbspy.vo.request.HeRequest;
import com.baoteng.rbspy.vo.request.InsureDetailsRequest;
import com.baoteng.rbspy.vo.request.PayQrCodeRequset;
import com.baoteng.rbspy.vo.request.UserInfo;
import com.baoteng.rbspy.vo.request.VehicleVO;
import com.baoteng.rbspy.vo.response.ApplyQuoteResponse;
import com.baoteng.rbspy.vo.response.CommonResponse;
import com.baoteng.rbspy.vo.response.FullUserInfo;
import com.baoteng.rbspy.vo.response.HeResponse;
import com.baoteng.rbspy.vo.response.PayQrResponse;
import com.baoteng.rbspy.vo.response.QuoteResult;
import com.baoteng.rbspy.vo.response.ReinfoResponse;
import com.baoteng.rbspy.vo.response.VehicleModelRestResponse;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Striped;

@Component
public class MessageHandler {

	@Autowired
	QuoteService quoteService;

	@Autowired
	RenewalService renewalService;
	
	@Autowired
	ProposalService proposalService;

	@Autowired
	RbSysConfig rbSysConfig;
	
	@Value("${redis.sub.senderTopic}")
	private String senderTopic;

	@Autowired
	StringRedisTemplate stringRedisTemplate;
	
	@Autowired
	LocalCacheManager statusCache;

	private long redisSubHeartbeatTimeStamp = System.currentTimeMillis();
	
	private final Logger logger = LoggerFactory.getLogger(MessageHandler.class);

	private static final Striped<Lock> payStriped = Striped.lazyWeakLock(256);
	
	private ReinfoResponse renewalHandler(RenewalPO response) {
		ReinfoResponse reinfo = new ReinfoResponse();
		reinfo.setBusinessStatus(0);
		reinfo.setStatusMessage("not found");
		if(response!=null) {
			reinfo.setBusinessStatus(1);
			reinfo.setStatusMessage("ok");
			FullUserInfo userInfo = new FullUserInfo();
			VehiclePO vehicle =response.getVehiclePO();
			userInfo.setRegisterDate(vehicle.getEnrollDate());
			userInfo.setSeatCount(vehicle.getSeatCount());
			userInfo.setPurchasePrice(vehicle.getPurchasePrice());
			userInfo.setBizNo(response.getBiNo());
			userInfo.setForceNo(response.getCiNo());
			userInfo.setCarVin(vehicle.getVinNo());
			userInfo.setEngineNo(vehicle.getEngineNo());
			userInfo.setLicenseNo(vehicle.getLicenseNo());
			userInfo.setModelCode(vehicle.getModelCode());
			userInfo.setModleName(vehicle.getModelName());
			userInfo.setExhaustScale(vehicle.getExhaustScale()!=null?String.format("%01.3f", vehicle.getExhaustScale()):null);
			try {
				if(StringUtils.isNotBlank(vehicle.getLicenseColorCode())) {
					userInfo.setLicenseColor(Integer.valueOf(vehicle.getLicenseColorCode()));
				}
				if(StringUtils.isNotBlank(vehicle.getClauseType()) && vehicle.getClauseType().length()>=1) {
					userInfo.setProofType(Integer.valueOf(vehicle.getClauseType().substring(vehicle.getClauseType().length()-1)));
				}
			} catch (NumberFormatException e) {
				logger.error("MessageHandler renewalHandler error.",e);
			}
			if(response.getBiEndDate()!=null) userInfo.setBusinessExpireDate(Date.from(response.getBiEndDate().atZone(ZoneId.systemDefault()).toInstant()));
			if(response.getCiEndDate()!=null) userInfo.setForceExpireDate(Date.from(response.getCiEndDate().atZone(ZoneId.systemDefault()).toInstant()));
			reinfo.setUserInfo(userInfo);
			
			if(response.getBi()!=null && response.getBi().getKinds()!=null && response.getBi().getKinds().size()>0) {
				final QuoteResult saveQuote = new QuoteResult();
				response.getBi().getKinds().forEach(kind->{
					switch(kind.getKindCode()) {
					case "050202"://车损
						saveQuote.setDamage(kind.getAmount());
						break;
					case "050501"://盗抢
						saveQuote.setRobbery(kind.getAmount());
						break;
					case "050602"://三者
						saveQuote.setThirdPartyAmount(kind.getAmount());
						break;
					case "050711"://车上人员责任险（司机）
						saveQuote.setDriverAmount(kind.getAmount());
						break;
					case "050712"://车上人员责任险（乘客）
						if(kind.getUnitAmount()!=null) {
							saveQuote.setPassengerAmount(kind.getUnitAmount());
						}else {
							saveQuote.setPassengerAmount(kind.getAmount());
						}
						break;
					case "050211"://车身划痕损失险
						saveQuote.setScratch(kind.getAmount());
						break;
					case "050232"://玻璃单独破碎险 
						if("20".equals(kind.getModeCode())) {
							saveQuote.setGlass(1d);
						}else {
							saveQuote.setGlass(0d);
						}
						break;
					case "050253"://指定修理厂险
						saveQuote.setDesignatedService(1d);
						break;
					case "050311"://自燃损失险
						saveQuote.setFire(kind.getAmount());
						break;
					case "050451"://无法找到第三方特约险
						saveQuote.setHcSanFangTeYue(1d);
						break;
					case "050461"://发动机涉水损失险
						saveQuote.setEngine(1d);
						break;
					case "050930"://不计免赔险（车损险）
						saveQuote.setNoRejectDamage(1d);
						break;
					case "050931"://不计免赔险（三者险）
						saveQuote.setNoRejectThirdParty(1d);
						break;
					case "050933"://不计免赔险（车上人员（司机））
						saveQuote.setNoRejectDriver(1d);
						break;
					case "050934"://不计免赔险（车上人员（乘客））
						saveQuote.setNoRejectPassenger(1d);
						break;
					case "050932"://不计免赔险（盗抢险）
						saveQuote.setNoRejectRobbery(1d);
						break;
					case "050937"://不计免赔险（车身划痕损失险）
						saveQuote.setNoRejectScratch(1d);
						break;
					case "050938"://不计免赔险（发动机涉水损失险）
						saveQuote.setNoRejectEngine(1d);
						break;
					case "050935"://不计免赔险（自燃损失险）
						saveQuote.setNoRejectFire(1d);
						break;
					}
				});
				reinfo.setSaveQuote(saveQuote);
			}
			reinfo.setBusPolicyNum(response.getBiNo());
			reinfo.setForPolicyNum(response.getCiNo());
			if(response.getPrivyPO()!=null && response.getPrivyPO().getItems()!=null && response.getPrivyPO().getItems().size()>0) {
				response.getPrivyPO().getItems().forEach(privy->{
					//关系人标志 11100010000000000000000000000A 第一位投保人 被保险人 车主 指定驾驶人 受益人 港澳车车主 联系人  投保人最后一位为A其它为0
					String flag = privy.getInsuredFlag();
					if(StringUtils.isNotBlank(flag) && flag.length()>=3) {
						UserInfo owner = new UserInfo();
						owner.setIdNo(privy.getIdentifyNumber());
						owner.setName(privy.getInsuredName());
						owner.setMobile(privy.getMobileNoYG());
						owner.setAddress(privy.getInsuredAddress());
						owner.setAge(StringUtils.isNotBlank(privy.getAge())?Integer.valueOf(privy.getAge()):null);
						owner.setEmail(privy.getEmail());
						
//						owner.setCustomerType(customerType);
						//关系人类型 1--个人 2--团体
						if("1".equals(privy.getInsuredType())) {
							owner.setUserType(1);
							owner.setCustomerType("01");
							if("03".equals(privy.getIdentifyType())){
								owner.setCustomerType("02");
							}
						}else {
							owner.setUserType(2);
							owner.setIdNo(privy.getUnifiedSocialCreditCode());
							if("100".equals(privy.getUnitType())) {
								owner.setOrganizationType("05");
							}else {
								owner.setOrganizationType("04");
							}
							owner.setCustomerType("01");
						}
						if("1".equals(flag.substring(0, 1))) {
							reinfo.setToubao(owner);
							userInfo.setHolderIdCard(owner.getIdNo());
							userInfo.setPostedName(owner.getName());
							userInfo.setHolderMobile(owner.getMobile());
							userInfo.setHolderIdType(owner.getCustomerType()!=null?Integer.valueOf(owner.getCustomerType()):2);
						}
						if("1".equals(flag.substring(1, 2))) {
							reinfo.setBeibao(owner);
							userInfo.setInsuredIdCard(owner.getIdNo());
							userInfo.setInsuredName(owner.getName());
							userInfo.setInsuredMobile(owner.getMobile());
							userInfo.setHolderIdType(owner.getCustomerType()!=null?Integer.valueOf(owner.getCustomerType()):2);
						}
						if("1".equals(flag.substring(2, 3))) {
							reinfo.setOwner(owner);
							userInfo.setLicenseOwner(owner.getName());
							userInfo.setCredentislasNum(owner.getIdNo());
							userInfo.setIdType(owner.getCustomerType()!=null?Integer.valueOf(owner.getCustomerType()):2);
						}
					}
				});
			}
		}
		return reinfo;
	}
	
	public void consumer(String message) {
		logger.info("message Received <{}> from publisher.", message);
		if (message.indexOf(PackageEntity.VEHICLE.getTypeId()) > -1) {
			WSPackage<VehicleVO> request = JsonUtils.parseJson(message,
					new TypeReference<WSPackage<VehicleVO>>() {
					});

			if (request == null || request.getData() == null) {
				logger.error("message consumer parse " + PackageEntity.VEHICLE.getTypeDesc() + "error.");
				return;
			}
			switch (request.getType()) {
			case GET:
				RenewalRequest _request = new RenewalRequest();
				_request.setLicenseNo(request.getData().getCarNum());
				_request.setLicenseType("02");
				RenewalPO response = renewalService.getRenewalInfo(_request);
				WSPackage<ReinfoResponse> _response = new WSPackage<ReinfoResponse>();
				copyStatus(request, _response);
				_response.setData(renewalHandler(response));
				producer(_response);
				break;
			default:
			}
		}else if (message.indexOf(PackageEntity.QUOTED.getTypeId()) > -1) {
			WSPackage<ApplyInsureRequest> request = JsonUtils.parseJson(message,
					new TypeReference<WSPackage<ApplyInsureRequest>>() {
					});

			if (request == null || request.getData() == null) {
				logger.error("message consumer parse " + PackageEntity.QUOTED.getTypeDesc() + "error.");
				return;
			}
			switch (request.getType()) {
			case GET:
				try {
					request.getData().setUserId(request.getUserId());
					request.getData().setWsId(request.getSessionId());
					request.getData().setBizId(request.getBizid());
					ApplyQuoteResponse response = quoteService.quote(request.getData());
					
					if (response == null) {
						producer(exceptionHandler(new BizException("报价失败，请联系客服"), request));
					}
					if(response.getBusinessStatus()!=null && response.getBusinessStatus()!= 2000) {
						WSPackage<ApplyQuoteResponse> _response = new WSPackage<ApplyQuoteResponse>();
						copyStatus(request, _response);
						_response.setType(PackageType.SET);
						_response.setData(response);
						producer(_response);
					}
				} catch (Exception e) {
					producer(exceptionHandler(e, request));
					logger.error(e.getMessage(), e);
				}
				break;
			default:
			}
		} else if (message.indexOf(PackageEntity.ORDER.getTypeId()) > -1) {
			WSPackage<HeRequest> _request = JsonUtils.parseJson(message, new TypeReference<WSPackage<HeRequest>>() {
			});
			if (_request == null || _request.getData() == null) {
				logger.error("message consumer parse " + PackageEntity.ORDER.getTypeDesc() + " error.");
				return;
			}
			switch (_request.getType()) {
			case GET:
				try {
					WSPackage<HeRequest> request = JsonUtils.parseJson(message, new TypeReference<WSPackage<HeRequest>>() {
					});
					HeResponse response = proposalService.submitUndwrt(request);

					if (response == null) {
						producer(exceptionHandler(new BizException("核保失败，请联系客服"), request));
						return;
					}
					WSPackage<HeResponse> _response = new WSPackage<HeResponse>();
					copyStatus(request, _response);
					_response.setData(response);
					producer(_response);
				} catch (Exception e) {
					producer(exceptionHandler(e, _request));
					logger.error(e.getMessage(), e);
				}
				break;
			case LIST:
				try {
					WSPackage<InsureDetailsRequest> request = JsonUtils.parseJson(message, new TypeReference<WSPackage<InsureDetailsRequest>>() {
					});
					if(request!=null && request.getData()!=null && request.getData().getNumbers()!=null) {
						List<String> numbers = request.getData().getNumbers();
						if(InsureDetailsRequest.Flag.PROPOSAL.getName().equals(request.getBizid())) {
							Optional<List<InfoProposal>> proposals = statusCache.getPproposalStatus();
							proposals.ifPresent(p->{
								p.forEach(_p->{
									System.out.println("picc proposals"+_p.getProposalNo());
								});
							});
							proposals.ifPresent(p->{
								numbers.forEach(number->{
									p.parallelStream().filter(e->{
										if(number.indexOf(e.getProposalNo())>-1) {
											try {
												HeResponse response = new HeResponse(0, "待核保");
												if (e.getUnderWriteFlag().contains("待缴费")) {
													response.setBusinessStatus(1);
													response.setStatusMessage("ok");
													if(e.getProposalNo().indexOf("DAA")!=-1) {
														response.setBusNum(e.getProposalNo());
													}else {
														response.setForceNum(e.getProposalNo());
													}
													DetailsProposal detail = proposalService.getProposalInfo(e.getProposalNo());
													response.setSumPremium(detail.getSumPremium());
													response.setSumPayTax(detail.getSumPayTax());
													response.setSumPay(BaseUtil.getMoneyNumber(detail.getSumPremium().doubleValue()+(detail.getSumPayTax()!=null?detail.getSumPayTax().doubleValue():0)));
												}  else if (!e.getUnderWriteFlag().contains("初始值") && !e.getUnderWriteFlag().contains("待核保")
														&& !e.getUnderWriteFlag().contains("自动核保通过")) {
													response = proposalService.getUndwrtInfo(number);
												}
												if(response!=null) {
													WSPackage<HeResponse> _response = new WSPackage<HeResponse>();
													copyStatus(request, _response);
													_response.setData(response);
													producer(_response);
												}
											} catch (Exception e1) {
												logger.error("order consumer proposal list error. msg:{};  ex:{}",message,e1);
											}
											return true;
										}else {
											return false;
										}
									}).findFirst();
								});
							});
						}else if(InsureDetailsRequest.Flag.POLICY.getName().equals(request.getBizid())) {
							Optional<List<InfoPolicy>> policies = statusCache.getPolicyStatus();
							final List<String> policyNos = Lists.newArrayList();
							policies.ifPresent(p->{
								numbers.forEach(number->{
									final List<String> proposals = Arrays.stream(number.split(",")).filter(proposal->{
										return !Strings.isNullOrEmpty(proposal);
									}).collect(Collectors.toList());
									policyNos.clear();
									final HeResponse response = new HeResponse(1, "ok");
									p.parallelStream().forEach(e->{
										if(number.indexOf(e.getProposalNo())>-1) {
											try {
												policyNos.add(e.getPolicyNo());
												if(e.getPolicyNo().indexOf("DAA")>-1)  response.setBusNum(e.getPolicyNo());
												else  response.setForceNum(e.getPolicyNo());
												if(policyNos.size()== proposals.size()) {
													response.setQuoteNum(number);
													DetailsProposal detail = proposalService.getProposalInfo(proposals.get(0));
													InfoFlow flow = proposalService.getFlow(proposals.get(0));
													if(detail!=null) {
														response.setSumPremium(detail.getSumPremium());
														response.setSumPayTax(detail.getSumPayTax());
														response.setSumPay(BaseUtil.getMoneyNumber(detail.getSumPremium().doubleValue()+(detail.getSumPayTax()!=null?detail.getSumPayTax().doubleValue():0)));
														response.setPayTime(flow!=null && flow.getPayTime()!=null?flow.getPayTime():null);
														WSPackage<HeResponse> _response = new WSPackage<HeResponse>();
														copyStatus(request, _response);
														_response.setData(response);
														producer(_response);
													}
												}
											} catch (Exception e1) {
												logger.error("order consumer policy list error. msg:{};  ex:{}",message,e1);
											}
										}
									});
								});
							});
						}
					}
				} catch (Exception e) {
					producer(exceptionHandler(e, _request));
					logger.error(e.getMessage(), e);
				}
				break;
			default:
			}
		} else if (message.indexOf(PackageEntity.PAYMENT.getTypeId()) > -1) {
			WSPackage<PayQrCodeRequset> request = JsonUtils.parseJson(message, new TypeReference<WSPackage<PayQrCodeRequset>>() {
			});
			if (request == null || request.getData() == null) {
				logger.error("message consumer parse " + PackageEntity.PAYMENT.getTypeDesc() + " error.");
				return;
			}
			switch (request.getType()) {
			case GET:
				String quoteNum = StringUtils.isNotBlank(request.getData().getBusNum())?request.getData().getBusNum():(StringUtils.isNotBlank(request.getData().getForNum())?request.getData().getForNum():request.getData().getQuoteNum());
				Lock prePayLock = payStriped.get(quoteNum);
				try {
					prePayLock.lock();
					PayQrResponse response = proposalService.getExchange(request.getData());

					if (response == null) {
						producer(exceptionHandler(new BizException("生成支付二维码失败，请联系客服"), request));
					}
					WSPackage<PayQrResponse> _response = new WSPackage<PayQrResponse>();
					copyStatus(request, _response);
					_response.setData(response);
					producer(_response);
				} catch (Exception e) {
					producer(exceptionHandler(e, request));
					logger.error(e.getMessage(), e);
				}finally {
					prePayLock.unlock();
				}
				break;
			default:
			}
		}else if(message.indexOf("rb spy heartbeat request")!=-1) {
			redisSubHeartbeatTimeStamp = System.currentTimeMillis();
			logger.info("PiccService receiveMessageHandler heartbeat message:{},redisSubHeartbeatTimeStamp:{} ................",message,redisSubHeartbeatTimeStamp);
		}else {
			logger.info("PiccService receiveMessageHandler error!!messgae is empty................");
		}
	}

	public void sendQuote(ApplyQuoteResponse response) {
		WSPackage<ApplyQuoteResponse> _response = new WSPackage<ApplyQuoteResponse>();
		_response.setEntity(PackageEntity.QUOTED);
		_response.setType(PackageType.GET);
		_response.setUserId(response.getUserId());
		_response.setSessionId(response.getWsId());
		_response.setBizid(response.getBizId());
		_response.setData(response);
		producer(_response);
	}
	
	public void producer(Object msg) {
		String strMsg = JsonUtils.toJsonString(msg);
		stringRedisTemplate.convertAndSend(senderTopic, strMsg);
		logger.info("producer send message. detail: {}", strMsg);
	}

	public WSPackage<?> exceptionHandler(Exception e, WSPackage<?> request) {
		WSPackage<CommonResponse> _e = new WSPackage<CommonResponse>();
		copyStatus(request, _e);
		if (e instanceof BizException) {
			_e.setData(new CommonResponse(-1, e.getMessage(), new Date()));
		} else if(e instanceof VehicleCodeException){
			String msg = e.getMessage();
			String[] msgs = msg.split(",");
			VehicleModelRestResponse response = new VehicleModelRestResponse();
			response.setBusinessStatus(-10);
			response.setStatusMessage(msgs!=null && msgs.length>=2 && !Strings.isNullOrEmpty(msgs[1])?msgs[1].replace("是否使用平台返回车型", ""):"所选车型与平台车型不一致");
			response.setTime(new Date());
			response.setResetModelCode(msgs!=null && msgs.length>=3?msgs[2]:null);
			_e.setData(response);
		} else {
			_e.setData(new CommonResponse(-2, e.getMessage(), new Date()));
		}
		return _e;
	}

	private void copyStatus(WSPackage<?> request, WSPackage<?> response) {
		response.setSessionId(request.getSessionId());
		response.setUserId(request.getUserId());
		response.setBizid(request.getBizid());
		response.setEntity(request.getEntity());
		response.setType(request.getType());
	}

	public long getRedisSubHeartbeatTimeStamp() {
		return redisSubHeartbeatTimeStamp;
	}

	public void setRedisSubHeartbeatTimeStamp(long redisSubHeartbeatTimeStamp) {
		this.redisSubHeartbeatTimeStamp = redisSubHeartbeatTimeStamp;
	}
	
	
}
